﻿using HttpLib.Util;
using IdentityModel;
using IdentityServer.Data.Repositories;
using IdentityServer4.Models;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using WeChatIdentity.Models;

namespace IdentityServer
{
    public class ProfileService : IProfileService
    {
        private readonly IHttpContextAccessor _context;
        private readonly UserManager<ApplicationUser> _userManager;
        public ProfileService(IHttpContextAccessor context,
            UserManager<ApplicationUser> userManager)
        {
            _context = context;
            _userManager = userManager;
        }
        async public Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject));
            var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;
            //var user = await _repository.GetUserAsync(subjectId);

            var user = await _userManager.FindByIdAsync(subjectId);
            if (user == null)
                throw new ArgumentException("Invalid subject identifier");
            var claims = await GetClaimsFromUser(user);
            context.Subject = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(JwtClaimTypes.Subject, claims.FirstOrDefault(t => t.Type == JwtClaimTypes.Subject).Value) }));
            context.IssuedClaims = claims.ToList();
        }
        async public Task IsActiveAsync(IsActiveContext context)
        {
            var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject));

            var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;
            var user = await _userManager.FindByIdAsync(subjectId);
            context.IsActive = false;
            if (user != null)
            {
                if (_userManager.SupportsUserSecurityStamp)
                {
                    var security_stamp = subject.Claims.Where(c => c.Type == "security_stamp").Select(c => c.Value).SingleOrDefault();
                    if (security_stamp != null)
                    {
                        var db_security_stamp = await _userManager.GetSecurityStampAsync(user);
                        if (db_security_stamp != security_stamp)
                            return;
                    }
                }
                context.IsActive = !user.LockoutEnabled || !user.LockoutEnd.HasValue || user.LockoutEnd <= DateTime.Now;
                #region 签名验证
                //#if DEBUG
                //                context.IsActive =
                //                    !user.LockoutEnabled ||
                //                    !user.LockoutEnd.HasValue ||
                //                    user.LockoutEnd <= DateTime.Now;
                //#else
                //            //验证签名
                //            var headers = _context.HttpContext.Request.Headers;
                //            string appKey = string.Empty,
                //                signature = string.Empty;
                //            var query = _context.HttpContext.Request.Query;
                //            foreach(var item in query)
                //            {
                //                if (item.Key.Equals("appkey"))
                //                {
                //                    appKey = item.Value;
                //                }
                //                else if (item.Key.Equals("signature"))
                //                {
                //                    signature = item.Value;
                //                }
                //            }
                //            if(!string.IsNullOrEmpty(appKey) && !string.IsNullOrEmpty(signature))
                //            {
                //                var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject));
                //                var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;
                //                bool validateResult = SignExtension.ValidateCode(subjectId, signature, appKey);
                //                if (validateResult)
                //                {
                //                    context.IsActive = true;
                //                    await Task.FromResult(true);
                //                }
                //            }
                //            context.IsActive = false;
                //            await Task.FromResult(false);
                //#endif
                #endregion
            }
        }
        private async Task<IEnumerable<Claim>> GetClaimsFromUser(ApplicationUser user)
        {
            var userClaims = await _userManager.GetClaimsAsync(user);
            string userRole = "";
            if (userClaims.Any())
            {
                foreach (var claim in userClaims.Where(t => t.Type == JwtClaimTypes.Role))
                {
                    userRole += claim.Value + ",";
                }
                userRole = userRole.TrimEnd(',');
            }
            var claims = new List<Claim>
            {
                new Claim(JwtClaimTypes.Role,userRole),//配置角色
                new Claim(JwtClaimTypes.Subject, user.Id),
                new Claim(JwtClaimTypes.PreferredUserName, user.UserName),
                new Claim(JwtRegisteredClaimNames.UniqueName, user.OpenId),
                new Claim(JwtClaimTypes.Name,user.UserName)
            };
            return claims;
        }
    }
}
